package net.asfun.jvalog.control;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import net.asfun.jvalog.frame.ReadCacheInterceptor;
import net.asfun.jvalog.service.CategoryService;
import net.asfun.jvalog.service.PageService;
import net.asfun.jvalog.service.PostService;
import net.asfun.jvalog.service.TagService;
import net.asfun.jvalog.util.TypeCaster;
import net.asfun.jvalog.vo.Category;
import net.asfun.jvalog.vo.Page;
import net.asfun.jvalog.vo.Pager;
import net.asfun.jvalog.vo.Post;
import net.asfun.jvalog.vo.Setting;
import net.asfun.jvalog.vo.Site;
import net.asfun.jvalog.vo.Tag;
import net.asfun.jvalog.mvc.RequestMapping;

public class ContentController{


	@RequestMapping({"", "*"})
	public String handleAll(HttpServletRequest req,
			Map<String, Object> model) throws Exception {
		
		String uri = (String)req.getAttribute(ReadCacheInterceptor.PATH_PARAM);	
		String arr[] = uri.split("/");

		switch(arr.length) {
		case 1:
			if ( "rss".equalsIgnoreCase(arr[0]) ||
				 "rss2".equalsIgnoreCase(arr[0]) ) {
				return this.rss(req, model);
			}
			if ( "atom".equalsIgnoreCase(arr[0]) || 
				 "feed".equalsIgnoreCase(arr[0]) ) {
				return this.feed(req, model);
			}
			if ( "sitemap".equalsIgnoreCase(arr[0]) ) {
				return this.sitemap(req, model);
			}
			if ( "404".equals(arr[0]) ) {
				return this.notFound(req, model);
			}
			if ( "500".equals(arr[0]) ) {
				return this.error(req, model);
			}
			if ( arr[0].matches("\\d{4}") ) {
				return this.date(req, model, arr[0]);
			}
			return this.index(req, model, 0);
		case 2:
			if ( "category".equalsIgnoreCase(arr[0]) ) {
				String slogan = getSlogan(arr[1]);
				return this.category(req, model, slogan, 0);
			}
			if ( "tag".equalsIgnoreCase(arr[0]) ) {
				String slogan = getSlogan(arr[1]);
				return this.tag(req, model, slogan, 0);
			}
			if ( "post".equalsIgnoreCase(arr[0]) ) {
				int page = TypeCaster.toInt(getSlogan(arr[1]));
				return this.index(req, model, page);
			}
			if ( "page".equalsIgnoreCase(arr[0]) ) {
				String slogan = getSlogan(arr[1]);
				return this.page(req, model, slogan);
			}
			if ( arr[0].matches("\\d{4}") && arr[1].matches("\\d{2}") ) {
				return this.date(req, model, arr[0], arr[1]);
			}
			return this.notFound(req, model);
		case 3:
			if ( "category".equalsIgnoreCase(arr[0]) ) {
				String slogan = getSlogan(arr[1]);
				int page = TypeCaster.toInt(getSlogan(arr[2]));
				return this.category(req, model, slogan, page);
			}
			if ( "tag".equalsIgnoreCase(arr[0]) ) {
				String slogan = getSlogan(arr[1]);
				int page = TypeCaster.toInt(getSlogan(arr[2]));
				return this.tag(req, model, slogan, page);
			}
			if ( arr[0].matches("\\d{4}") && arr[1].matches("\\d{2}")
					&& arr[2].matches("\\d{2}") ) {
				return this.date(req, model, arr[0], arr[1], arr[2]);
			}
			return this.notFound(req, model);
		case 4:
			if ( arr[0].matches("\\d{4}") && arr[1].matches("\\d{2}")
					&& arr[2].matches("\\d{2}") ) {
				return this.post(req, model);
			}
			return this.notFound(req, model);
		default:
			return this.notFound(req, model);
		}

	}

	private String error(HttpServletRequest req, Map<String, Object> model) {
		return "500.html";
	}

	private String post(HttpServletRequest req, Map<String, Object> model) {
		String uri = (String) req.getAttribute(ReadCacheInterceptor.PATH_PARAM);
		model.put("post", PostService.getByUri(uri));
		return "post.html";
	}

	private String date(HttpServletRequest req, Map<String, Object> model,
			String... ymd) {
		model.put("title", arrayJoin(ymd, "-"));
		//TODO 分页
		Pager pager = new Pager();
		model.put("posts", PostService.listArchive(pager, ymd));
		model.put("pager", pager);
		return "date.html";
	}

	private String notFound(HttpServletRequest req,
			Map<String, Object> model) {
		return "404.html";
	}

	private String category(HttpServletRequest req,
			Map<String, Object> model, String slogan, int page) {
		Category category = CategoryService.getBySlogan(slogan);
		Pager pager = new Pager(page);
		model.put("posts", CategoryService.listPublished(category, pager));
		model.put("category", category);
		model.put("pager", pager);
		return "category.html";
	}

	private String tag(HttpServletRequest req, Map<String, Object> model,
			String slogan, int page) {
		Tag tag = TagService.getBySlogan(slogan);
		Pager pager = new Pager(page);
		model.put("posts", TagService.listPublished(tag, pager));
		model.put("tag", tag);
		model.put("pager", pager);
		return "tag.html";
	}

	private String feed(HttpServletRequest req, Map<String, Object> model) {
		model.put("posts", PostService.listRecent(Setting.SIZE_ATOM));
		return "atom.xml";
	}

	private String sitemap(HttpServletRequest req,
			Map<String, Object> model) {
		List<HashMap<String,Object>> urlset = new ArrayList<HashMap<String,Object>>();
		HashMap<String,Object> main = new HashMap<String,Object>();
		main.put("location", Site.getInstance().getUrl());
		main.put("lastmod",new Date());
		main.put("changefreq", "daily");
		main.put("priority", 0.9);
		urlset.add(main);
		List<Page> pages = PageService.listPublished();
		for(Page page : pages) {
			HashMap<String,Object> url = new HashMap<String,Object>();
			url.put("location", page.getLink());
			url.put("lastmod", page.getDate());
			url.put("changefreq", "monthly");
			url.put("priority", 0.8);
			urlset.add(url);
		}
		List<Post> posts = PostService.listRecent(Setting.SIZE_MAP);
		for(Post post : posts) {
			HashMap<String,Object> url = new HashMap<String,Object>();
			url.put("location", post.getLink());
			url.put("lastmod", post.getDate());
			url.put("changefreq", "never");
			url.put("priority", 0.7);
			urlset.add(url);
		}
		List<Category> cates = CategoryService.listAll();
		for(Category cate : cates) {
			HashMap<String,Object> url = new HashMap<String,Object>();
			url.put("location", cate.getLink());
			url.put("changefreq", "weekly");
			url.put("priority", 0.5);
			urlset.add(url);
		}
		List<Tag> tags = TagService.listAll();
		for(Tag tag : tags) {
			HashMap<String,Object> url = new HashMap<String,Object>();
			url.put("location", tag.getLink());
			url.put("changefreq", "weekly");
			url.put("priority", 0.4);
			urlset.add(url);
		}
		model.put("urlset", urlset);
		return "sitemap.xml";
	}

	private String rss(HttpServletRequest req, Map<String, Object> model) {
		model.put("posts", PostService.listRecent(Setting.SIZE_RSS));
		return "rss.xml";
	}

	private String page(HttpServletRequest req, Map<String, Object> model,
			String slogan) {
		model.put("page", PageService.getBySlogan(slogan));
		return "page.html";
	}

	private String index(HttpServletRequest req, Map<String, Object> model,
			int page) {
		Pager pager = new Pager(page);
		model.put("posts", PostService.listPublished(pager));
		model.put("pager", pager);
		return "index.html";
	}
	
	private String getSlogan(String str) throws UnsupportedEncodingException {
		return URLDecoder.decode(str, "utf-8");
	}
	
	private String arrayJoin(String[] arr, String conn) {
		StringBuffer buff = new StringBuffer();
		for(int i=0; i< arr.length; i++) {
			buff.append(arr[i]);
			if ( i < arr.length - 1 ) {
				buff.append(conn);
			}
		}
		return buff.toString();
	}
}
